/* file: lexer.h*/

%{
  #include <iostream>
  #include <cerrno>
  #include <climits>
  #include <cstdlib>
  #include <string>

  #include "parser.hpp"  //包含由parser.y生成的头文件
  #include "scanner.h"   //包含yyFlexLexer子类的头文件
  #include "location.hh" //包含位置调试信息头文件
  #include "ast.h"

  static Marker::location loc;//声明位置实例
  #define YY_USER_ACTION  loc.columns (yyleng); /* 定义了YY_USER_ACTION，该宏在每个记号的语义动作之前被调用，来根据记号的长度设置位置的信息 */

  #undef yywrap
  #define yywrap() 1

  using namespace Marker;
  #define yyterminate() Parser::make_END(loc);
%}
/* 声明使用C++版本FLEXER，c++是大小写不敏感的 */
%option c++

/* 支持调试 */
%option noyywrap debug

/* 使用Scanner::yylex() */
%option yyclass="Scanner"

/* 一些与编译常量使用该前缀否则为yy */
%option prefix="Marker_"

/*正则式的各种简写，使程序有层次感而显得明晰 */
EXP ([Ee][-+]?[0-9]+)
string      \"[^\n"]+\"
/**/
ws          [ \t]+
alpha       [A-Za-z]
dig         [0-9]
name        ({alpha}|_)({alpha}|{dig}|_)*
exp         ([Ee][-+]?[0-9]+)
num1        [0-9]+\.[0-9]*{EXP}?
num2        \.?[0-9]+{EXP}?
number      {num1}|{num2}

%%
%{
    loc.step();
%}
"+"         {return Parser::make_ADD(Marker::Parser::token::TOKEN_ADD, loc);}
"-"         {return Parser::make_SUB(Marker::Parser::token::TOKEN_SUB, loc);}
"*"         {return Parser::make_MUL(Marker::Parser::token::TOKEN_MUL, loc);}
"/"         {return Parser::make_DIV(Marker::Parser::token::TOKEN_DIV, loc);}
"="         {return Parser::make_EQL(Marker::Parser::token::TOKEN_EQL, loc);}       
"|"         {return Parser::make_ABS(Marker::Parser::token::TOKEN_ABS, loc);}
","         {return Parser::make_COM(loc);}
";"         {return Parser::make_SEM(loc);}
"("         {return Parser::make_LP(loc);}
")"         {return Parser::make_RP(loc);}
"{"         {return Parser::make_LB(loc);}
"}"         {return Parser::make_RB(loc);}
">"         {return Parser::make_CMP(1, loc);}
"<"         {return Parser::make_CMP(2, loc);}
"<>"        {return Parser::make_CMP(3, loc);}
"=="        {return Parser::make_CMP(4, loc);}
">="        {return Parser::make_CMP(5, loc);}
"<="        {return Parser::make_CMP(6, loc);}
"||"        {return Parser::make_LOR(Marker::Parser::token::TOKEN_LOR, loc);}
"&&"        {return Parser::make_LAND(Marker::Parser::token::TOKEN_LAND, loc);}

"if"        {return Parser::make_IF(loc);}
"else"      {return Parser::make_ELSE(loc);}
"while"     {return Parser::make_WHILE(loc);}
"let"       {return Parser::make_LET(loc);}

"sqrt"      {return Parser::make_FUNC(Fncall::bifs::B_sqrt, loc);}
"exp"       {return Parser::make_FUNC(Fncall::bifs::B_exp, loc);}
"log"       {return Parser::make_FUNC(Fncall::bifs::B_log, loc);}
"print"     {return Parser::make_FUNC(Fncall::bifs::B_print, loc);}
{name}      {return Parser::make_NAME(Symbol::lookup(std::string(yytext)), loc);}
{number}    { std::string yytextStr(yytext);return Parser::make_NUMBER(std::make_shared<Numval>(std::stod(yytextStr)), loc);}
"//".* |
[ \t]       {loc.step();}
"\\n"        {loc.step();}
\n          {loc.step();loc.begin.column = 1; loc.end.column = 1;return Parser::make_EOL(loc);}
<<EOF>>   { return yyterminate(); }
.           {std::cout << "Mystery character " << yytext[0] << std::endl;}
%%
//这里可以放一些C或者C++代码